#include <iostream>
#include <fstream>
#include "lib/binary_tree.h"
using namespace std;

bool readStream(istream &ifile, int &num) {
  if (ifile.eof())
    return false;

  char buff[32];
  buff[0] = '\0';

  char ch;
  int i = 0;
  while (ifile >> ch && ch != ',') {
    buff[i++] = ch;
  }

  if (i > 0 && buff[0] != '$') {
    num = atoi(buff);
    return true;
  }
  return false;
}

void serialize(BinaryTreeNode* root, ostream &ofile) {
  if (!root) {
    ofile << "$,";
    return;
  }
  ofile << root->value << ',';
  serialize(root->left, ofile);
  serialize(root->right, ofile);
}

void deserialize(BinaryTreeNode* &root, istream &ifile) {
  int num = 0;
  if (readStream(ifile, num)) {
    root = new BinaryTreeNode();
    root->value = num;
    root->left = nullptr;
    root->right = nullptr;

    deserialize(root->left, ifile);
    deserialize(root->right, ifile);
  }
}

bool isSame(BinaryTreeNode* root1, BinaryTreeNode* root2) {
  if (!root1 && !root2)
    return true;
  if (!root1 || !root2)
    return false;
  if (root1->value != root2->value)
    return false;
  
  return isSame(root1->left, root2->left) &&
         isSame(root1->right, root2->right);
}

bool test(BinaryTreeNode* root, BinaryTreeNode* deserialize_root) {
  string filename = "test_serialize_and_deserialize";
  ofstream ofile;
  ofile.open(filename);
  serialize(root, ofile);
  ofile.close();

  // print to screen
  serialize(root, cout);
  cout << '\n' << endl;

  ifstream ifile;
  ifile.open(filename);
  deserialize(deserialize_root, ifile);
  ifile.close();

  // print deserialize tree
  PrintBinaryTree(deserialize_root);
  
  return isSame(root, deserialize_root);
}

int main() {
  vector<int> vec = {1, 2, 3, 4, 5, 6, 7};
  BinaryTreeNode* root = CreateBinaryTree(vec);

  BinaryTreeNode* deserialize_root = nullptr;
  bool ret = test(root, deserialize_root);
  cout << "Test result: " << ret << endl;

  DeleteBinaryTree(root);
  DeleteBinaryTree(deserialize_root);
}
